package com.baiyun.service.impl;

import cn.hutool.json.JSONUtil;
import com.baiyun.domain.Menu;
import com.baiyun.domain.MenuDTO;
import com.baiyun.domain.User;
import com.baiyun.mapper.MenuMapper;
import com.baiyun.mapper.UserMapper;
import com.baiyun.service.MenuService;
import com.baiyun.service.UserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 20516
 * @description 针对表【sys_menu】的数据库操作Service实现
 * @createDate 2022-06-17 21:40:01
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu>
        implements MenuService {

    @Autowired
    UserService userService;

    @Autowired
    UserMapper userMapper;

    @Override
    public List<MenuDTO> getCurrentUserNav() {
        String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = userService.getByUsername(username);

        List<Long> menuIds = userMapper.getNavMenuIds(user.getId());
        List<Menu> menus = this.listByIds(menuIds);

        // 转树状结构
        List<Menu> menuTree = buildTreeMenu(menus);

        // 实体转DTO
        return convert(menuTree);
    }

    @Override
    public List<Menu> tree() {
        //获取所以菜单信息
        List<Menu> menus = this.list(new QueryWrapper<Menu>().orderByAsc("orderNum"));
        //转成树状结构
        return buildTreeMenu(menus);
    }

    private List<MenuDTO> convert(List<Menu> menuTree) {
        List<MenuDTO> menuDTOS = new ArrayList<>();
        menuTree.forEach(m -> {
            MenuDTO dto = new MenuDTO();
            dto.setId(m.getId());
            dto.setName(m.getPerms());
            dto.setIcon(m.getIcon());
            dto.setTitle(m.getName());
            dto.setComponent(m.getComponent());
            dto.setPath(m.getPath());

            if (m.getChildren().size() > 0) {
                dto.setChildren(convert(m.getChildren()));
            }
            menuDTOS.add(dto);
        });
        return menuDTOS;
    }

    private List<Menu> buildTreeMenu(List<Menu> menus) {
        /*List<Menu> finalMenus = new ArrayList<>();
        List<Menu> sonMenus = new ArrayList<>();
        // 先各自寻找到各自的孩子
        for (Menu menu : menus) {

            for (Menu e : menus) {
                if (menu.getId() == e.getParentId()) {
                    menu.getChildren().add(e);
                }
            }

            // 提取出父节点
            if (menu.getParentId() == 0L) {
                finalMenus.add(menu);
            }
        }
        System.out.println(JSONUtil.toJsonStr(finalMenus));
        return finalMenus;*/

        //创建list集合，用于数据最终封装
        List<Menu> finalNode = new ArrayList<>();
        //把所有菜单list集合遍历，得到顶层菜单 pid=0菜单，设置level是1
        for (Menu menu : menus) {
            //得到顶层菜单 pid=0菜单
            if (menu.getParentId() == 0) {
                //根据顶层菜单，向里面进行查询子菜单，封装到finalNode里面
                finalNode.add(selectChildren(menu, menus));
            }
        }
        System.out.println("---------->" + JSONUtil.toJsonStr(finalNode));
        return finalNode;
    }

    private Menu selectChildren(Menu menu, List<Menu> menus) {
        //1 因为向一层菜单里面放二层菜单，二层里面还要放三层，把对象初始化
        menu.setChildren(new ArrayList<Menu>());
        //2 遍历所有菜单list集合，进行判断比较，比较id和pid值是否相同
        for (Menu it : menus) {
            //判断 id和pid值是否相同
            if (menu.getId().equals(it.getParentId())) {
                //如果children为空，进行初始化操作
                if (menu.getChildren() == null) {
                    menu.setChildren(new ArrayList<Menu>());
                }
                //把查询出来的子菜单放到父菜单里面
                //permissionNode.getChildren().add(it);
                //这样只对一层子菜单进行添加，此时应递归调用，进行多层子菜单添加。
                menu.getChildren().add(selectChildren(it, menus));
            }
        }
        return menu;
    }
}




